home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (c) 1987 University of Maryland Department of Computer Science.
- * All rights reserved. Permission to copy for any purpose is hereby granted
- * so long as this copyright notice remains intact.
- */
-
- /*
- * Conversions. Conversion factors convert between values in scaled
- * points and values in device-dependenent units. The results of all
- * conversions are rounded to the nearest integral value, of type (i32).
- */
-
- /*
- * This is now done using `double' values, but may be changed to
- * fixed-point or some other `fast' method, as long as the results
- * are consistent and reasonably accurate. The structure `conversion'
- * holds the conversion-method-dependent quantities; the macros
- * fromSP and toSP apply the conversion to a value. (Note that
- * fromSP and toSP need not be macros, but should be fast.)
- *
- * SetConversion sets the (single, global) conversion factor.
- * If a driver needs special conversions, there is another routine,
- * CSetConversion that sets a specific conversion, and cfromSP and
- * ctoSP to apply these.
- *
- * IS USING DOTS PER INCH SUFFICIENT? (Pixels per point might be better.)
- *
- * Note that it is necessary to set the global conversion factor before
- * using any fonts.
- */
- struct conversion {
- double c_fromsp; /* multiplier to convert from scaled points */
- double c_tosp; /* multiplier to convert to scaled points:
- could divide by c_fromsp, but this should
- be faster and more accurate */
- double c_mag; /* the magnification this conversion
- represents; mainly for GetFont() */
- double c_dpi; /* dpi (should be pixels per point?) */
- } Conversion;
-
- /*
- * In order to do this, we need to round properly. The compilers I
- * have tend to generate very poor code for this. The following is
- * intended to help them out. Smarter compilers can do better, but
- * if they are smart enough, they will realise that the variables
- * here are not used anywhere else, and discard them. (For a compiler
- * to do this given separate compliation, `static' is a must.)
- */
- #ifdef lint /* or a smart compiler */
- #define ROUND(f) ((i32) ((f) < 0.0 ? (f) - 0.5 : (f) + 0.5))
- #define CEIL(f) ((double) (i32) (f) < (f) ? (i32) (f) + 1 : (i32) (f))
- #else
- static double _half = 0.5;
- static double _zero = 0.0;
- static double _d;
- #define ROUND(f) ((i32) (_d = (f), _d < _zero ? _d - _half : _d + _half))
- #ifdef NEGATIVE_FLOAT_ROUNDS_TO_NEGATIVE_INFINITY
- #define CEIL(f) (-(i32) -(f))
- #else /* we will assume that floating to integer truncates */
- static i32 _i;
- #define CEIL(f) (_i = _d = (f), _i < _d ? _i + 1 : _i)
- #endif /* round towards negative infinity */
- #endif /* lint */
-
- #define SetConversion(dpi, usermag, num, denom, dvimag) \
- CSetConversion(&Conversion, dpi, usermag, num, denom, dvimag)
-
- #define cfromSP(c, v) ROUND((c)->c_fromsp * (v))
- #define ctoSP(c, v) ROUND((c)->c_tosp * (v))
-
- #define fromSP(v) cfromSP(&Conversion, v)
- #define toSP(v) ctoSP(&Conversion, v)
-
- /*
- * Conversions for rules are a bit different: we must round up, rather
- * than off. ConvRule applies the global conversion value for a rule
- * value (height or width); CConvRule applies a specific conversion.
- */
- #define CConvRule(c, v) CEIL((c)->c_fromsp * (v))
- #define ConvRule(v) CConvRule(&Conversion, v)
-
- void CSetConversion();
-